import 'dart:io';
import 'package:dio/dio.dart';
import 'package:get/get.dart' hide FormData, MultipartFile;
import 'package:path/path.dart' as path;
import 'package:image/image.dart' as img;
import 'package:path_provider/path_provider.dart';
import 'base_service.dart';

/// 文件上传服务类
class FileService extends GetxService {
  final BaseService _baseService = BaseService();

  /// 上传头像图片 - 专门为头像优化的上传方法
  Future<Map<String, dynamic>> uploadAvatarImage(File imageFile) async {
    try {
      print('开始处理头像图片...');

      // 压缩图片
      final compressedFile = await _compressImage(imageFile);

      // 上传压缩后的图片
      final result = await uploadFile(compressedFile);

      // 清理临时文件
      if (compressedFile.path != imageFile.path) {
        try {
          await compressedFile.delete();
        } catch (e) {
          print('清理临时文件失败: $e');
        }
      }

      return result;
    } catch (e) {
      print('上传头像图片失败: $e');
      rethrow;
    }
  }

  /// 压缩图片
  Future<File> _compressImage(File imageFile) async {
    try {
      print('开始压缩图片: ${imageFile.path}');

      // 读取原始图片
      final originalBytes = await imageFile.readAsBytes();
      final originalSize = originalBytes.length;
      print('原始图片大小: ${(originalSize / 1024).toStringAsFixed(2)} KB');

      // 如果图片小于500KB，不需要压缩
      if (originalSize < 500 * 1024) {
        print('图片大小合适，无需压缩');
        return imageFile;
      }

      // 解码图片
      final image = img.decodeImage(originalBytes);
      if (image == null) {
        print('无法解码图片，使用原图');
        return imageFile;
      }

      // 计算新的尺寸（最大800x800，保持比例）
      int newWidth = image.width;
      int newHeight = image.height;
      const int maxSize = 800;

      if (newWidth > maxSize || newHeight > maxSize) {
        if (newWidth > newHeight) {
          newHeight = (newHeight * maxSize / newWidth).round();
          newWidth = maxSize;
        } else {
          newWidth = (newWidth * maxSize / newHeight).round();
          newHeight = maxSize;
        }
      }

      // 调整图片尺寸
      final resizedImage = img.copyResize(
        image,
        width: newWidth,
        height: newHeight,
      );

      // 压缩图片（JPEG格式，质量75）
      final compressedBytes = img.encodeJpg(resizedImage, quality: 75);
      final compressedSize = compressedBytes.length;
      print('压缩后图片大小: ${(compressedSize / 1024).toStringAsFixed(2)} KB');
      print(
        '压缩比例: ${((1 - compressedSize / originalSize) * 100).toStringAsFixed(1)}%',
      );

      // 保存压缩后的图片到临时文件
      final tempDir = await getTemporaryDirectory();
      final tempFile = File(
        '${tempDir.path}/compressed_avatar_${DateTime.now().millisecondsSinceEpoch}.jpg',
      );
      await tempFile.writeAsBytes(compressedBytes);

      return tempFile;
    } catch (e) {
      print('压缩图片失败: $e，使用原图');
      return imageFile;
    }
  }

  /// 文件上传 - 优化版本，支持重试和更长超时
  Future<Map<String, dynamic>> uploadFile(File file) async {
    const int maxRetries = 3;
    int currentRetry = 0;

    while (currentRetry < maxRetries) {
      try {
        print(
          '开始上传文件: ${file.path}, 大小: ${await _getFileSize(file)} KB, 尝试次数: ${currentRetry + 1}/$maxRetries',
        );

        // 检查文件是否存在
        if (!await file.exists()) {
          throw Exception('文件不存在');
        }

        // 检查文件大小（限制为10MB）
        final fileSize = await file.length();
        if (fileSize > 10 * 1024 * 1024) {
          throw Exception('文件大小超过10MB限制');
        }

        // 创建FormData
        final fileName = path.basename(file.path);
        final formData = FormData.fromMap({
          'file': await MultipartFile.fromFile(file.path, filename: fileName),
        });

        // 设置上传专用的超时配置
        final uploadOptions = Options(
          headers: {'Content-Type': 'multipart/form-data'},
          sendTimeout: const Duration(minutes: 5), // 上传超时5分钟
          receiveTimeout: const Duration(minutes: 2), // 接收超时2分钟
        );

        final response = await _baseService.post<Map<String, dynamic>>(
          '/file/fileUpload',
          data: formData,
          options: uploadOptions,
        );

        if (response.data != null) {
          final data = response.data!;
          if (data['code'] == 0 && data['success'] == true) {
            print('文件上传成功: $fileName');
            return data;
          } else {
            throw Exception(data['msg'] ?? '文件上传失败');
          }
        } else {
          throw Exception('文件上传响应数据为空');
        }
      } on DioException catch (e) {
        print('文件上传网络错误 (尝试 ${currentRetry + 1}/$maxRetries): ${e.message}');
        print('网络错误详情: ${_getDetailedErrorMessage(e)}');

        // 如果是连接重置错误且还有重试机会，则重试
        if (_shouldRetry(e) && currentRetry < maxRetries - 1) {
          currentRetry++;
          await Future.delayed(Duration(seconds: currentRetry * 2)); // 递增延迟
          continue;
        } else {
          throw Exception('网络环境不佳，请稍后尝试');
        }
      } catch (e) {
        print('文件上传错误: $e');
        throw Exception(
          e.toString().contains('文件大小超过') ? e.toString() : '网络环境不佳，请稍后尝试',
        );
      }
    }

    throw Exception('网络环境不佳，请稍后尝试');
  }

  /// 获取文件大小（KB）
  Future<double> _getFileSize(File file) async {
    final bytes = await file.length();
    return bytes / 1024;
  }

  /// 判断是否应该重试
  bool _shouldRetry(DioException e) {
    // 连接重置、超时、网络不可达等错误可以重试
    return e.type == DioExceptionType.connectionTimeout ||
        e.type == DioExceptionType.sendTimeout ||
        e.type == DioExceptionType.receiveTimeout ||
        e.type == DioExceptionType.connectionError ||
        (e.message?.contains('Connection reset by peer') ?? false) ||
        (e.message?.contains('Connection refused') ?? false) ||
        (e.message?.contains('Network is unreachable') ?? false);
  }

  /// 获取详细的错误信息
  String _getDetailedErrorMessage(DioException e) {
    switch (e.type) {
      case DioExceptionType.connectionTimeout:
        return '连接超时';
      case DioExceptionType.sendTimeout:
        return '发送超时';
      case DioExceptionType.receiveTimeout:
        return '接收超时';
      case DioExceptionType.connectionError:
        return '连接错误';
      case DioExceptionType.badResponse:
        return '服务器响应错误: ${e.response?.statusCode}';
      case DioExceptionType.cancel:
        return '请求被取消';
      case DioExceptionType.unknown:
        return '未知错误: ${e.message}';
      default:
        return e.message ?? '网络错误';
    }
  }

  /// 获取文件访问地址
  Future<Map<String, dynamic>> getFileUrl(String path) async {
    try {
      final response = await _baseService.get<Map<String, dynamic>>(
        '/file/getFileUrl',
        queryParameters: {'path': path},
      );

      if (response.data != null) {
        final data = response.data!;
        if (data['code'] == 0 && data['success'] == true) {
          return data;
        } else {
          throw Exception(data['msg'] ?? '获取文件地址失败');
        }
      } else {
        throw Exception('获取文件地址响应数据为空');
      }
    } on DioException catch (e) {
      print('获取文件地址网络错误: ${e.message}');
      throw Exception('网络环境不佳，请稍后尝试');
    } catch (e) {
      print('获取文件地址错误: $e');
      throw Exception('网络环境不佳，请稍后尝试');
    }
  }
}
